一家單店的租書店,兩位店員,目前用紙本出租卡。老闆想把它變成一套程式。
把這件事交給AI,問法只差幾句,拿到的東西差很遠。
第一種問法:
幫我設計一個租書系統的資料庫。
拿到的是一張十幾張資料表的ER圖:書籍、分類、作者、出版社、會員、會員等級、借閱、預約、罰款、庫存異動……每一張都設計得很合理,欄位齊全,關聯正確。
第二種問法:
一家單店的租書店,兩位店員,目前用紙本出租卡。
只需要記錄誰借了哪本書、何時借出、何時歸還。
請先不要給資料表,只列出你認為必要的名詞,以及每個名詞在紙卡上對應的欄位。
拿到的是三個名詞。
兩次的回答看起來都合理。第一張圖的關聯未必有錯,錯的是它回答了一間不存在的店:沒有人告訴它這家店只有兩位店員、老闆手上那疊卡片上面到底寫了什麼、以及「預約」這件事店裡從來沒發生過。照那張圖做下去,會多做一大批這家店現在用不到的資料表。
這三十天練的就是這一段:程式碼怎麼寫,AI比筆者快得多;但這家店現在該做到哪裡、哪些東西是三年後才需要的、以及手上這份程式碼撐不撐得住店裡的真實資料量——這些它不知道,因為它沒去過那家店。
從那疊紙卡開始,一步一步走到資料庫,最後五天回頭算AI那筆帳:
第 2~8 天 紙卡 → 老闆晚上數哪些書還沒回來
Console → 第一版櫃檯程式,資料只活在記憶體裡
試算表 → 老闆問:用Excel不行嗎
檔案 → 關機就忘了,資料要存下來
第 9~11 天 斷電 → 店員關機時正在寫檔,隔天五百筆打不開
第 12~24 天 量測 → 店開到第三年,早上開機要多等一下
SQLite → 換掉文字檔,但理由不是「比較快」
索引 → 建好了,查詢時間沒有變
移轉 → 兩邊對帳,刪一列就報 490 個假問題
罰金 → 老闆調漲逾期費率,已經收過的錢變了
第 25~29 天 提問 → 同一件事問AI兩次,一次拿到十幾張資料表,一次拿到三個名詞
第 30 天 結帳 → 三十天量過什麼、還欠什麼
第二天到第二十四天,每一天都在替下一步做一次選擇。不是「介紹某個技術」,是「店裡出了什麼事,所以現在要決定一件事」。結論常常是「還不需要」——第三年的店用不到的東西,第三年就不該進場。
最後五天不講程式,講提問。前面每一個決策當初都問過AI,低品質的問法和高品質的問法各留了一份紀錄,那五天把它們攤開來對照。
四個部分固定:
效能和容量的說法一律附實測數字,用固定隨機種子產生的同一組資料,並且註明規模和機器。文章裡不會出現「快很多」這種講法。
舉一個實際發生過的例子。第十二天老闆會問一句「再開下去會怎樣」,筆者把借閱筆數從一千拉到四十萬,量早上開機要等多久。同一張表改了三次才敢用,每一次改的都不是程式,是量法。
第一版的表跑出來很整齊,但不能用:書固定在兩千種、只放大借閱筆數,等於把這家店開了五十三年,一百萬筆裡只剩三筆未歸還——那個數字量到的是資料被拉變形,不是程式變慢。第二次改量存檔,數字漂亮得可疑:程式把資料交給作業系統就算完成,這時還不能保證資料真的進了硬碟;要求作業系統真的寫進硬碟之後,量到的才是店員在等的那段時間。第三次發現在這組量測裡第一輪固定比較慢,之後便固定丟掉第一輪不計入。
第一版資料失真,第二版沒有量到真的寫進硬碟,第三版排除第一輪之後才採用。三版的長相一樣專業,只有第三版可以拿出來。只把結果表交給AI,它攔不住前兩版——它沒有那台機器,也不知道那份資料是怎麼長出來的。第十三天會把這三版完整走一遍。
程式碼從第三天開始出現,之後每一篇會對應一個git tag,取得出來、跑得起來,也可以和前一篇比對差異。
因為它夠小,小到三十天講得完;也夠真,真到每一個技術問題都有一個店裡的對應物。借閱不是一張範例資料表,它是卡片上的一行;「未歸還」不是一個布林欄位,它是老闆晚上要數的那一疊。
而且它會長大。店開第一年、第三年、第十年,同一份程式碼會遇到不同的問題——這正是選型會失效的地方。今天選對的東西明年不一定還對,而知道它什麼時候會失效,比知道它現在是對的更有用。
從那疊紙卡開始。三個名詞不是設計出來的,是抄下來的。
這個系列是筆者正在寫的一套教學內容的濃縮版;完整版含每一次量測的原始輸出與更長的決策紀錄,三十天結束後會繼續往下走。